////////////////////////////////////////////
// PerformanceTimer.h
// Author : Brent Chua
//
///////////////////////////////////////////

#ifndef _PERFORMANCE_TIMER_H_
#define _PERFORMANCE_TIMER_H_

///////////////////
// Classes/Structs
class PerformanceTimer;
class TimerAccumulator;
class FPS;

class PerformanceTimer
{
public:
	PerformanceTimer(void);
	~PerformanceTimer(void);

	void Initialize();

	float Update(void);

	float DeltaTime(void);

	void Pause(void);

	void Resume(void);

	void Reset(void);

	inline bool IsPaused(void);

	inline void SetPaused(bool paused);

private:

	__int64 m_cntsPerSec;
	__int64 m_currTimeStamp;
	__int64 m_prevTimeStamp;
	float m_secsPerCnt;
	float m_deltaTime;
	bool m_paused;
};

/////////////////
// Inline implementations
bool PerformanceTimer::IsPaused()
{
	return m_paused;
}

void PerformanceTimer::SetPaused(bool paused)
{
	m_paused = paused;
}

////////////////////////////////////////////////////////////////////////////////////
// Brief:	Timer Accumulator
// Details: Since frequently calling QueryPerformanceCounter takes a conssiderable
//			amount of processing time, this class is designed to only accumulate
//			elapsed time by passing deltaTime in update and doesn't calcuates delta 
//			time on its	own.
class TimerAccumulator
{
public:

	inline void Update(float dt);
	inline void Reset(void);

protected:
	float elapsedTime;
};

/////////////////////////
// Inline implementations
void TimerAccumulator::Update(float dt)
{
	elapsedTime += dt;
}

void TimerAccumulator::Reset(void)
{
	elapsedTime = 0.0f;
}


///////////////////////////////////
// Brief: TargetedTimerAccumulator
class TimerCountdown
{
public:

	inline void setStartTime(float _targetTime);
	
	inline bool Update(float dt);

	inline bool IsDone(void);

	inline void Restart(void);

	// Brief: Restart timeCoundown to startTime.
	inline void Reset(void);

private:
	float startTime;
	float timeCountdown;
};

/////////////////////////
// Inline implementations
void TimerCountdown::setStartTime(float _startTime)
{
	startTime = _startTime;
}

bool TimerCountdown::Update(float dt)
{
	return ((timeCountdown -= dt) <= 0.0f);
}

bool TimerCountdown::IsDone(void)
{
	return timeCountdown <= 0.0f;
}

void TimerCountdown::Restart(void)
{
	timeCountdown = startTime;
}

void TimerCountdown::Reset(void)
{
	startTime = timeCountdown = 0.0f;
}


/////////////////////
// Brief: FPS counter
class FPS
{
public:
	inline FPS();

	void Update(float dt);

	inline void Reset(void);

	inline unsigned int GetFPS(void);

private:

	unsigned int fps;
	unsigned int frameCount;
	float elapsedTime;

};

/////////////////////////
// Inline implementations
FPS::FPS(): frameCount(0) 
{
}

void FPS::Reset(void)
{
	frameCount = 0;
	elapsedTime = 0.0f;
}

unsigned int FPS::GetFPS(void)
{
	return fps;
}

#endif /* _PERFORMANCE_TIMER_H_ */